package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"
)

// HandleFunc 视图函数签名
type HandleFunc func(ctx *Context)
type server interface {
	http.Handler
	Start(addr string) error
	Stop() error
	addRouter(method string, pattern string, handleFunc HandleFunc)
}

type HTTPOption func(h *HttpServer)
type HttpServer struct {
	srv  *http.Server
	stop func() error
	//routers map[string]HandleFunc
	*router
}

func WithHttpServerStop(fn func() error) HTTPOption {
	return func(h *HttpServer) {
		if fn == nil {
			fn = func() error {
				quit := make(chan os.Signal)
				signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
				<-quit
				log.Println("Shutdown Server ...")
				ctx, cancelFunc := context.WithTimeout(context.Background(), 5*time.Second)
				defer cancelFunc()
				if err := h.srv.Shutdown(ctx); err != nil {
					log.Fatal("Server Shutdown:", err)
				}
				select {
				case <-ctx.Done():
					log.Println(" timeout of 5 seconds")
				}
				return nil
			}
		}
		h.stop = fn
	}
}
func NewHttp(opts ...HTTPOption) *HttpServer {
	httpServer := &HttpServer{router: newRouter()}
	for _, opt := range opts {
		opt(httpServer)
	}
	return httpServer
}

// ServeHttp接受请求 转发请求
// 接受请求 前端传过来的请求
// ServeHTTP方法向前对接前端请求  向后对接后端框架
func (h *HttpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// 1.匹配路由
	n, ok := h.getRouter(r.Method, r.URL.Path)
	if !ok {
		w.WriteHeader(http.StatusNotFound)
		w.Write([]byte("404"))
		return
	}
	//构造当前请求的上下文
	content := NewContent(w, r)
	fmt.Sprintf("request %s  -%s\n", r.Method, r.URL.Path)
	// 找到了 转发请求
	n.handleFunc(content)
}

func (h *HttpServer) Start(addr string) error {
	h.srv = &http.Server{Addr: addr, Handler: h}
	return h.srv.ListenAndServe()
}

func (h *HttpServer) Stop() error {
	return h.stop()
}

// addRouter注册路由
// 注册路由的时机：就是项目启动得时候注册，项目启动之后就不能注册了
//
//	func (h *HttpServer) addRouter(method string, pattern string, handleFunc HandleFunc) {
//		key := fmt.Sprintf("%s-%s", method, pattern)
//		h.routers[key] = handleFunc
//	}
func (h *HttpServer) Get(pattern string, handleFunc HandleFunc) {
	h.addRouter(http.MethodGet, pattern, handleFunc)
}

func (h *HttpServer) Post(pattern string, handleFunc HandleFunc) {
	h.addRouter(http.MethodPost, pattern, handleFunc)
}
func (h *HttpServer) DELETE(pattern string, handleFunc HandleFunc) {
	h.addRouter(http.MethodDelete, pattern, handleFunc)
}
func (h *HttpServer) PUT(pattern string, handleFunc HandleFunc) {
	h.addRouter(http.MethodPut, pattern, handleFunc)
}
